/*!
 * jquery dynamic tab plugin
 * 
 * version: 1.0 
 * author: Daniel  
 * 
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 * 
 * Usage example:
 * 	HTML:
 * 		<div class="ft_outer">
 *			<div class="nav_container"></div>
 *			<div id="dialog_container"></div>
 *      </div>
 *   JS:
 *		var tab = $('.ft_outer').dynamicTab({
 *			tabbarContainer: $('.nav_container')
 *			,tabPanelContainer: $('#dialog_container')
 *			,tabbarClass:'contactTabbar'
 *			,tabcontentClass:'contactTabcontent'});
 *		tab.dynamicTab('addTab', 'tab title 1', '<div>tab content 1</div>', 'tabId1');
 *		tab.dynamicTab('addTab', 'tab title 2', '<div>tab content 2</div>', 'tabId2');
 * 
 *    其它说明：之所以使用visibility属性来隐藏或显示，是为了当panel里面有swf元素时，在chrome中用display元素会导致swf每次都重新加载
 * 			   使用该CSS属性后，需要注意panel容器必须写样式	position: absolute; bottom: 0; top: 0; left: 0; right: 0;	
 */
(function($) {

	var dynamicTab = {
		
		_tabNum: 0
		
		,_allTabsWidth: 0
		
		,_visibleWidth: 0
		
		,_tabContainer: null
		
		,_latestWidth: 0  //最后一次宽度
		
		,_showClass: {'visibility':'visible', 'z-index':'0'}
		
		,_hideClass: {'visibility':'hidden', 'z-index':'-1'}
		
		,events: {
			changeSelectedTab: "changeSelectedTab"
			,closeLastTab: "closeLastTab"
			,closeTab: "closeTab"
		}
		
		// These options will be used as defaults
		,options: {
			tabbarContainer: null
			,tabPanelContainer: null
			,tabbarClass: 'tabbar'
			,tabcontentClass: 'tabcontent'
			,showSeparator: false
			,enablePage: true
		}
		
		,_create: function() {
			this._tabContainer = $(this.element[0]);
			this._latestWidth = this._tabContainer.width();

			var wrapDiv	= $('<div/>').addClass(this.options.tabbarClass).css({position:'relative'});	
			var wrapBarDiv = $('<div/>').addClass('tabsDisplay').css({overflow:'hidden', width:($(this._tabContainer).width()-40)+'px', position:'relative'});
			var wrapBarUl = $('<ul/>').addClass('tabsDisplay').css({width:'5000px', position:'relative'});
			var wrapPageUl = $('<ul><li><a class="prev"></a></li><li><a class="next"></a></li></ul>').addClass('pageControl').css({position:'absolute', display:'none', right:0, top:0});
			
			wrapBarDiv.append(wrapBarUl);
			wrapDiv.append(wrapBarDiv);
			if (this.options.enablePage) {
				wrapDiv.append(wrapPageUl);
			}
			this.options.tabbarContainer.append(wrapDiv);
			this.options.tabPanelContainer.addClass(this.options.tabcontentClass);
			this._visibleWidth = wrapBarDiv.width();
			
			wrapBarUl.sortable({axis: 'x', tolerance: 'pointer'});
			
			if (this.options.enablePage) {
				this._bindEvents();
			}
		}
		
		,_setOption: function(key, value) {
			$.Widget.prototype._setOption.apply(this, arguments);
		}
		
		,_bindEvents: function() {
			var resizeTimeout
			 	,self = this
			 	,tabContainer = this._tabContainer
			 	,tabbarUL = $('ul.tabsDisplay', tabContainer)
			 	,prevBtn = $('.prev', tabContainer)
			 	,nextBtn = $('.next', tabContainer)
				,intervalId;
			
			prevBtn.bind({
				mouseover: function(event) {
					if ($(this).hasClass('prev-disabled')) {
						return false;
					}
					
					if (nextBtn.hasClass('next-disabled')) {
						nextBtn.removeClass('next-disabled');
					}
					
					intervalId = setInterval(function() {
						var curMarginLeft = parseFloat(tabbarUL.css('margin-left'));
						if (curMarginLeft >= 0) {
							clearInterval(intervalId);
							prevBtn.addClass('prev-disabled');
						} else {
							tabbarUL.animate({marginLeft: '+=10'}, 90, 'linear');
						}
					},100);
				}
				,mouseout: function(event) {
					clearInterval(intervalId);
				}
			});			
			nextBtn.bind({
				mouseover: function(event) {
					if ($(this).hasClass('next-disabled')) {
						return false;
					}
					
					if (prevBtn.hasClass('prev-disabled')) {
						prevBtn.removeClass('prev-disabled');
					}					
					
					intervalId = setInterval(function() {
						var curMarginLeft = -parseFloat(tabbarUL.css('margin-left'));
						if (curMarginLeft+self._visibleWidth >= self._allTabsWidth) {
							clearInterval(intervalId);
							nextBtn.addClass('next-disabled');
						} else {
							tabbarUL.animate({marginLeft: '-=10'}, 90, 'linear');
						}
					},100);
				}
				,mouseout: function(event) {
					clearInterval(intervalId);
				}
			});
			
			$(window).resize(function(){
				clearTimeout(resizeTimeout);
				resizeTimeout = setTimeout(function() {
				    self.update();
				}, 150);
			});
		}
	
		,update: function() {
			var tabContainer =  this._tabContainer;
			var tabPageUL = $("ul.pageControl", tabContainer);
			var tabbarDIV = $("div.tabsDisplay", tabContainer);
			var tabbarUL = $('ul.tabsDisplay', tabContainer);
			var tabbarClass = this.options.tabbarClass;
			var curMarginLeft = -parseFloat(tabbarUL.css('margin-left'));
			
			if (this._latestWidth == tabContainer.width()) {  //宽度没变化，不需要更新
				return;
			}
			
			if (this._allTabsWidth > $(tabContainer).width()) {
				this._visibleWidth = $(tabContainer).width() - tabPageUL.outerWidth(true);
				$("."+tabbarClass+" div.tabsDisplay", tabContainer).width(this._visibleWidth);
				
				if (tabPageUL.css('display') == 'none') {
					tabPageUL.show();
				} else {
					if (this._visibleWidth > this._allTabsWidth - curMarginLeft) {
						var nextBtn = $('.next', tabPageUL);
						nextBtn.addClass('next-disabled');
						tabbarUL.animate({marginLeft: -(this._allTabsWidth - this._visibleWidth)}, 'fast', 'linear'); 
					}
				}
			} else {
				this._visibleWidth = $(tabContainer).width();
				$("."+tabbarClass+" div.tabsDisplay", tabContainer).width(this._visibleWidth);
				if (tabPageUL.css('display') != 'none') {
    				tabPageUL.hide();
					tabbarDIV.width($(tabContainer).width());
					this.scrollToTab($('li', tabbarUL).eq(0)); //scroll to first tab
				}				
			}			
		}
		
		,checkTabExist: function(tabPandelId) {
			var tabContainer =  this._tabContainer;
			return tabContainer.find('#'+tabPandelId).length > 0 ? true : false;
		}
		
		/**
		 * @param tabTitle (string). for example: "tab1"
		 * @param tabPanel (html string). for example: "<div>tab content</div>"
		 * @param tabPanelId
		 * @param isFocus (boolean), default is true
		 * @param blockCloseFunc 阻止TAB关闭按钮的默认行为，当关闭前需要用户确认时需要用到，调用closeTab方法才可关闭
		 */
		,addTab: function(tabTitle, tabPanel, tabPanelId, isFocus, blockCloseFunc) {
			isFocus = isFocus == undefined ? true : isFocus;
			tabPanelId = tabPanelId == undefined ? new Date().getTime() : tabPanelId;
			
			var self = this;
			var tabbarClass = self.options.tabbarClass;
			var tabcontentClass = self.options.tabcontentClass;
			var showSeparator = self.options.showSeparator;
			var tabContainer =  self._tabContainer;
			var tabPageUL = $("ul.pageControl", tabContainer);
			var tabbarDIV = $("div.tabsDisplay", tabContainer).eq(0);  //avoid error when tab has tab
			var tabbarUL = $('ul.tabsDisplay', tabContainer).eq(0);  //avoid error when tab has tab
			var tabContentDIV = $("."+tabcontentClass, tabContainer);
			var icon = $('<span class="status online"></span>');
			var indicator = $('<span class="indicator"></span>');
			var closeIcon = $('<a class="close"></a>');
			var tab = $('<li/>', {id:'tab_' + tabPanelId}).html('<span class="title">' + tabTitle + '</span>');
			var panel = $('<div/>', {id:tabPanelId}).addClass('tabPanel').html(tabPanel);
			
			if (showSeparator && self._tabNum > 0) {
				tabbarUL.append('<li class="separator"><span></span></li>');
			}
			
			//append elements
			tab.append(closeIcon);
			tab.append(indicator);
			tab.prepend(icon);
			tabbarUL.append(tab);
			tabContentDIV.append(panel);
			
			//focus or not
			if (self._tabNum == 0 || isFocus) {
				$("."+tabbarClass+" ul.tabsDisplay li", tabContainer).removeClass("tab-selected");
				$("."+tabcontentClass+">div", tabContainer).css(self._hideClass);
				panel.css(self._showClass);
				tab.addClass("tab-selected");				
			} else {
				panel.css(self._hideClass);
			}
			
			//
			closeIcon.hide();
			self._tabNum += 1;
			self._allTabsWidth += tab.outerWidth(true);
			
			//
			if (self._allTabsWidth > $(tabContainer).width()) {
				if (tabPageUL.css('display') == 'none') {
					tabPageUL.show();
					
					self._visibleWidth = $(tabContainer).width() - tabPageUL.outerWidth(true);
					$("."+tabbarClass+" div.tabsDisplay", tabContainer).width(self._visibleWidth);
				}
				if (isFocus) self.scrollToTab(tab);
			}
			
			// ---  register events --- //
			tab.bind({
				click: function() {
				    $("."+tabbarClass+" ul.tabsDisplay li", tabContainer).removeClass("tab-selected");
				    $("."+tabcontentClass+">div", tabContainer).css(self._hideClass);
				    
				    tab.addClass("tab-selected");
				    panel.css(self._showClass);
				    
				    self.scrollToTab(tab);
				    
				    $(tabContainer).trigger(self.events.changeSelectedTab, [tabPanelId]);
				}
				,mouseover: function() {
					closeIcon.show();
				}
				,mouseout: function() {
					closeIcon.hide();
				}
			});
			
			closeIcon.bind("click", function(e, ignoreBlock) {
				
				if (!ignoreBlock) {
					if (blockCloseFunc && typeof(blockCloseFunc) == 'function') {
						blockCloseFunc();
						return;
					}
				}
				
				if (tab.hasClass("tab-selected")) {	//focus
					panel.css(self._hideClass);
					
					if (self._tabNum > 1) {
						var activeTab = (!tab.prev().length > 0 ? tab.next() : tab.prev());
						var activePanel = (!panel.prev().length > 0 ? panel.next() : panel.prev());
					    // activate other tab
					    activeTab.addClass("tab-selected");
					    activePanel.css(self._showClass);
					} 
				}
			    //
			    self._allTabsWidth -= tab.outerWidth(true);
			    self._tabNum -= 1;
			    tab.remove();
			    panel.remove();
			    //
    			if (self._allTabsWidth <= $(tabContainer).width()) {
    				tabPageUL.hide();
					tabbarDIV.width($(tabContainer).width());
					self.scrollToTab($('li', tabbarUL).eq(0)); //scroll to first tab
				} else {
					//判断最后一个TAB是否整个在可视区域里面，如果是，要将该TAB滑动到最右边
					var lastTab = tabbarUL.eq(self._tabNum-1);
					var subWidth = self._allTabsWidth - lastTab.outerWidth(true); //距离最后一个TAB之前的总宽度
					var curMarginLeft = -parseFloat(tabbarUL.css('margin-left'));
					var visibleWidth = self._visibleWidth;
					if (subWidth >= curMarginLeft && subWidth <= curMarginLeft + visibleWidth - lastTab.outerWidth(true)) { //最后一个TAB整个在可视区域里面
						tabbarUL.animate({marginLeft: -(subWidth - visibleWidth)}, 'fast', 'linear');
					}
				}
			    //
			    $(tabContainer).trigger(self.events.closeTab, tabPanelId);
			    if (self._tabNum == 0) {
			    	$(tabContainer).trigger(self.events.closeLastTab);
			    }
			    
			    return false;
			});			
		}
		
		,closeTab: function(tabPanelId) {
			var self = this;
			
			var tab = self.getTabByTabPanelId(tabPanelId);
			if (tab.length > 0) {
				tab.find('.close').trigger('click', true);
			}
		}
		
		,bind: function(event, handler) {
			if (this.events[event.split('.')[0]]) {
				var tabContainer = this._tabContainer;
				$(tabContainer).bind(event, handler);
			} else {
				alert('bind fail: no such event "' + event + '"');
			}
		}
		
		,unbind: function(event, handler) {
			if (this.events[event.split('.')[0]]) {
				var tabContainer = this._tabContainer;
				$(tabContainer).unbind(event, handler);
			} else {
				alert('bind fail: no such event "' + event + '"');
			}			
		}
		
		,addExtraStyleForTab: function(tab, className) {
			if ($(tab).length > 0) {
				$(tab).addClass(className);
			}
		}
		
		,removeExtraStyleForTab: function(tab, className) {
			if ($(tab).length > 0) {
				$(tab.removeClass(className));
			}
		} 
		
		/**
		 * return tab jquery oject
		 */
		,getTabByTabPanelId: function(tabPanelId) {
			var tabContainer = this._tabContainer;
			return $('[id="tab_' + tabPanelId + '"]', tabContainer);
		}
		
		,scrollToIdx: function(idx) {
			
			if (!this.options.enablePage) {
				return;
			}
			
			var tabContainer = this._tabContainer;
			var tabbarUL = $('ul.tabsDisplay', tabContainer);
			var tabs = $('li', tabbarUL);
			var tab = tabs.eq(idx);
			if (tabs.length <= idx) {
				alert('no tab in index:' + idx);
				return false;
			}
			
			var tabContainer = this._tabContainer;
			var tabPageUL = $("ul.pageControl", tabContainer);
			var prevBtn = $('.prev', tabPageUL);
			var nextBtn = $('.next', tabPageUL);

			var curMarginLeft = -parseFloat(tabbarUL.css('margin-left'));
			var allTabsWidth = this._allTabsWidth;
			var tabWidth = tab.outerWidth(true);
			var visibleWidth = this._visibleWidth;
			
			var totalWidth = 0; //该TAB之前的总宽度
			for (var i=0; i<idx; i++) {
				var item = tabs.eq(i);
				totalWidth += item.outerWidth(true);
			}
			
			if (totalWidth >= curMarginLeft && totalWidth <= curMarginLeft + visibleWidth - tabWidth) { //整个TAB在可视区域
				//do nothing.
			} else if (totalWidth <= curMarginLeft - tabWidth || totalWidth >= curMarginLeft + visibleWidth) { //整个TAB不在可视区域
				if (totalWidth <= curMarginLeft - tabWidth) { //往右边滑动
					tabbarUL.animate({marginLeft: -totalWidth}, 'fast', 'linear');
				} else { //往左边滑动
					tabbarUL.animate({marginLeft: -(totalWidth + tabWidth - visibleWidth)}, 'fast', 'linear');
				}
			} else { //TAB有一部分在可视区域，一部分处于不可视区域
				if (totalWidth > curMarginLeft) { //向左滑动
					tabbarUL.animate({marginLeft: -(totalWidth + tabWidth - visibleWidth)}, 'fast', 'linear');
				} else { //向右滑动
					tabbarUL.animate({marginLeft: -totalWidth}, 'fast', 'linear');
				}
			}
			
			//
			if (tabPageUL.css('display') != 'none') {
				if (idx == 0) { 
					prevBtn.addClass('prev-disabled');
					nextBtn.removeClass('next-disabled');
				} else if (idx == tabs.length - 1) {
					nextBtn.addClass('next-disabled');
					prevBtn.removeClass('prev-disabled');
				} else {
					prevBtn.removeClass('prev-disabled');
					nextBtn.removeClass('next-disabled');
				}			
			}
		}
		
		,scrollToTab: function(tab) {
			var tabContainer = this._tabContainer;
			var tabbarUL = $('ul.tabsDisplay', tabContainer);
			var tabs = $('li', tabbarUL);
			var idx = tabs.index(tab);
			this.scrollToIdx(idx);
		}
		
		,activeTab: function(tab) {
			if (tab.length > 0) {
				tab.trigger('click');
			}
		}
		
		,isTabSelected: function(tab) {
			if (tab.length > 0) {
				if (tab.hasClass('tab-selected')) {
					return true;
				}
				return false;
			} else {
				alert('param must a tab jquery object');
			}
		}
		
		,updateTabTitle: function(tab, title) {
			if ($(tab).length > 0) {
				tab.find('.title').text(title);
			}
		}
		
		,getSelectedTabPanel: function() {
			var tabContainer = this._tabContainer;
			var tabPanel = $('.tabPanel:not(:hidden)', tabContainer);
			return tabPanel;
		}
		
		,destroy: function() {
			$.Widget.prototype.destroy.call(this);
		}
	}	
	
	// The jQuery.aj namespace will automatically be created if it doesn't exist
	$.widget("ft.dynamicTab", dynamicTab);
})(jQuery);
